package com.dy.yunying.biz.service.hongbao.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.dy.yunying.api.constant.Constant;
import com.dy.yunying.api.entity.ParentGameArea;
import com.dy.yunying.api.entity.WanGameDO;
import com.dy.yunying.api.entity.hongbao.*;
import com.dy.yunying.api.resp.hongbao.NodeParentData;
import com.dy.yunying.api.vo.HbActivityCenterVO;
import com.dy.yunying.biz.dao.ads.hongbao.HbActivityCenterAreaMapper;
import com.dy.yunying.biz.dao.ads.hongbao.HbActivityCenterChannelMapper;
import com.dy.yunying.biz.dao.ads.hongbao.HbActivityCenterGameMapper;
import com.dy.yunying.biz.dao.ads.hongbao.HbActivityCenterMapper;
import com.dy.yunying.biz.dao.manage.ParentGameAreaMapper;
import com.dy.yunying.biz.dao.manage.ext.GameDOMapperExt;
import com.dy.yunying.biz.dao.manage.ext.ParentGameDOMapperExt;
import com.dy.yunying.biz.dao.manage.ext.PromotionChannelDOMapperExt;
import com.dy.yunying.biz.dao.manage.ext.WanGameChannelInfoDOMapperExt;
import com.dy.yunying.biz.service.hongbao.HbActivityCenterService;
import com.dy.yunying.biz.utils.DateUtils;
import com.dy.yunying.biz.utils.RedisLock;
import com.google.api.client.util.Lists;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author MyPC
 * @description 针对表【hb_activity_center(活动中心配置表)】的数据库操作Service实现
 * @createDate 2022-01-12 19:26:58
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HbActivityCenterServiceImpl extends ServiceImpl<HbActivityCenterMapper, HbActivityCenterDO> implements HbActivityCenterService {

	private static final Log MYBATIS_LOG = LogFactory.getLog(HbActivityCenterServiceImpl.class);

	private static final String HB_ACTIVITY_CENTER_EDIT_LOCK_MUTEX = "hb:activity:center:edit:key";

	private final HbActivityCenterMapper hbActivityCenterMapper;

	private final HbActivityCenterGameMapper hbActivityCenterGameMapper;

	private final HbActivityCenterAreaMapper hbActivityCenterAreaMapper;

	private final HbActivityCenterChannelMapper hbActivityCenterChannelMapper;

	private final GameDOMapperExt gameDOMapperExt;

	private final PromotionChannelDOMapperExt promotionChannelDOMapperExt;

	private final WanGameChannelInfoDOMapperExt wanGameChannelInfoDOMapperExt;

	private final ParentGameAreaMapper parentGameAreaMapper;

	private final ParentGameDOMapperExt parentGameDOMapperExt;

	private final RedisLock redisLock;

	/**
	 * 活动中心分页列表
	 *
	 * @param activityCenter
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, transactionManager = "adsTransactionManager")
	@Override
	public Page<HbActivityCenterDO> getPage(HbActivityCenterVO activityCenter) {
		final HbActivityCenterDO queryBean = new HbActivityCenterDO().setActivityName(activityCenter.getActivityName()).setSourceType(activityCenter.getSourceType()).setOrderByName(activityCenter.getOrderByName()).setOrderByAsc(Objects.equals(1, activityCenter.getOrderByAsc()) ? "ASC" : "DESC");
		Page<HbActivityCenterDO> page = hbActivityCenterMapper.selectActivityListBySelective(activityCenter, queryBean);
		this.findGameAreaChannel(page);
		return page;
	}

	/**
	 * 活动中心保存活动
	 *
	 * @param activityCenter
	 */
	@Transactional(rollbackFor = Exception.class, transactionManager = "adsTransactionManager")
	@Override
	public void doSave(HbActivityCenterVO activityCenter) {
		final String token = redisLock.tryLock(HB_ACTIVITY_CENTER_EDIT_LOCK_MUTEX, 30);
		if (StringUtils.isNotBlank(token)) {
			try {
				// 校验活动是否重复
				this.requireActivityUnique(activityCenter.getSourceType(), activityCenter.getActivityId(), null);
				this.validData(activityCenter.getSourceType(), activityCenter.getActivityType(), activityCenter.getDynamicTypeId());

				final int openType = activityCenter.getOpenType();
				final int showType = 2 == openType ? 2 : 0;

				// 保存活动信息
				final Long userId = Integer.toUnsignedLong(SecurityUtils.getUser().getId());
				final Date now = new Date();
				HbActivityCenterDO hbActivityCenterDO = new HbActivityCenterDO()
						.setUserGroupId(activityCenter.getUserGroupId())
						.setActivityName(activityCenter.getActivityName())
						.setSourceType(activityCenter.getSourceType())
						.setActivityType(activityCenter.getActivityType())
						.setActivityId(activityCenter.getActivityId())
						.setDynamicTypeId(activityCenter.getDynamicTypeId())
						.setActivityOrder(activityCenter.getActivityOrder())
						.setPromoteImageUri(activityCenter.getPromoteImageUri())
						.setOpenType(openType)
						.setShowType(showType)
						.setOpenUrl(3 == activityCenter.getSourceType() ? activityCenter.getOpenUrl() : "")
						.setStartTime(StringUtils.isNotBlank(activityCenter.getStartTime()) ? DateUtils.stringToDate(activityCenter.getStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS) : null)
						.setFinishTime(StringUtils.isNotBlank(activityCenter.getFinishTime()) ? DateUtils.stringToDate(activityCenter.getFinishTime(), DateUtils.YYYY_MM_DD_HH_MM_SS) : null)
						.setCreateTime(now)
						.setUpdateTime(now)
						.setCreateId(userId)
						.setUpdateId(userId);
				boolean flag = this.save(hbActivityCenterDO);
				if (flag) {
					if (3 == activityCenter.getSourceType().intValue()){
						activityCenter.setId(hbActivityCenterDO.getId());
						// 活动中心 游戏，区服，渠道关系
						this.saveGameAreaChannel(activityCenter);
					}
				}
			} finally {
				redisLock.unlock(HB_ACTIVITY_CENTER_EDIT_LOCK_MUTEX, token);
			}
		}
	}

	private void requireActivityUnique(int sourceType, Long activityId, Long ignoreId) {
		if (3 != sourceType) {
			int count = this.count(Wrappers.<HbActivityCenterDO>lambdaQuery()
					.eq(HbActivityCenterDO::getActivityId, activityId)
					.eq(HbActivityCenterDO::getSourceType, sourceType)
					.eq(HbActivityCenterDO::getDeleted, 0)
					.ne(Objects.nonNull(ignoreId), HbActivityCenterDO::getId, ignoreId));
			if (count > 0) {
				throw new NullPointerException("当前活动已存在活动中心");
			}
		}
	}

	private void validData(Integer sourceType, Integer activityType, Long dynamicTypeId){
		//红包活动，校验动态菜单和活动类型
		if(sourceType == 1){
			if(activityType == null){
				throw new NullPointerException("活动类型不能为空");
			}
			if(dynamicTypeId == null){
				throw new NullPointerException("活动动态类型ID不能为空");
			}
		}else{
			//签到活动不做校验
		}

	}


	/**
	 * 活动中心修改活动
	 *
	 * @param activityCenter
	 */
	@Transactional(rollbackFor = Exception.class, transactionManager = "adsTransactionManager")
	@Override
	public void doEdit(HbActivityCenterVO activityCenter) {
		final String token = redisLock.tryLock(HB_ACTIVITY_CENTER_EDIT_LOCK_MUTEX, 30);
		if (StringUtils.isNotBlank(token)) {
			try {
				// 查询出活动中心活动信息
				final long id = activityCenter.getId();
				final HbActivityCenterDO selectBean = this.getById(id);
				if (null == selectBean) {
					return;
				}
				final Integer sourceType = ObjectUtils.defaultIfNull(activityCenter.getSourceType(), selectBean.getSourceType());
				final Integer activityType = ObjectUtils.defaultIfNull(activityCenter.getActivityType(), selectBean.getActivityType());
				final Long activityId = ObjectUtils.defaultIfNull(activityCenter.getActivityId(), selectBean.getActivityId());
				final Long dynamicTypeId = ObjectUtils.defaultIfNull(activityCenter.getDynamicTypeId(), selectBean.getDynamicTypeId());

				final int openType = activityCenter.getOpenType();
				final int showType = 2 == openType ? 2 : 0;

				// 校验活动是否重复
				this.requireActivityUnique(sourceType, activityId, id);
				this.validData(sourceType, activityType, dynamicTypeId);

				final Long userId = Integer.toUnsignedLong(SecurityUtils.getUser().getId());
				final Date now = new Date();
				HbActivityCenterDO hbActivityCenterDO = new HbActivityCenterDO()
						.setId(id).setSourceType(sourceType)
						.setUserGroupId(activityCenter.getUserGroupId())
						.setActivityName(activityCenter.getActivityName())
						.setActivityType(activityType)
						.setActivityId(activityId)
						.setDynamicTypeId(dynamicTypeId)
						.setActivityOrder(activityCenter.getActivityOrder())
						.setPromoteImageUri(activityCenter.getPromoteImageUri())
						.setOpenType(openType)
						.setShowType(showType)
						.setOpenUrl(3 == sourceType.intValue() ? activityCenter.getOpenUrl() : "")
						.setStartTime(StringUtils.isNotBlank(activityCenter.getStartTime()) ? DateUtils.stringToDate(activityCenter.getStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS) : null)
						.setFinishTime(StringUtils.isNotBlank(activityCenter.getFinishTime()) ? DateUtils.stringToDate(activityCenter.getFinishTime(), DateUtils.YYYY_MM_DD_HH_MM_SS) : null)
						.setUpdateTime(now)
						.setUpdateId(userId);
				boolean flag = this.updateById(hbActivityCenterDO);
				if (flag) {
					if (3 == activityCenter.getSourceType().intValue()){
						activityCenter.setId(hbActivityCenterDO.getId());
						// 活动中心 游戏，区服，渠道关系
						this.saveGameAreaChannel(activityCenter);
					}
				}
			} finally {
				redisLock.unlock(HB_ACTIVITY_CENTER_EDIT_LOCK_MUTEX, token);
			}
		}
	}

	/**
	 * 活动中心删除活动
	 *
	 * @param id
	 */
	@Transactional(rollbackFor = Exception.class, transactionManager = "adsTransactionManager")
	@Override
	public void doDelete(Long id) {
		this.update(Wrappers.<HbActivityCenterDO>lambdaUpdate().set(HbActivityCenterDO::getDeleted, 1).eq(HbActivityCenterDO::getId, id));
	}

	/**
	 * 活动中心 游戏，区服，渠道关系
	 *
	 * @param activityCenter
	 */
	@Transactional(rollbackFor = Exception.class, transactionManager = "adsTransactionManager")
	public void saveGameAreaChannel(HbActivityCenterVO activityCenter) {
		Long activityCenterId = activityCenter.getId();
		Date date = new Date();
		if (Objects.isNull(activityCenterId)) {
			throw new NullPointerException("活动中心主键为空");
		}
		if (CollectionUtils.isNotEmpty(activityCenter.getChannelDataList())) {
			// 更新渠道关系
			List<HbActivityCenterChannel> insertList = Lists.newArrayList();
			HbActivityCenterChannel channel;
			for (String[] channelArr : activityCenter.getChannelDataList()) {
				if (channelArr.length > 0) {
					channel = new HbActivityCenterChannel();
					channel.setActivityCenterId(activityCenterId);
					if (1 == channelArr.length) {
						channel.setParentChl(channelArr[0]);
						channel.setChannelRange(1);
					}
					if (2 == channelArr.length) {
						channel.setParentChl(channelArr[0]);
						channel.setChl(channelArr[1]);
						channel.setChannelRange(2);
					}
					if (3 == channelArr.length) {
						channel.setParentChl(channelArr[0]);
						channel.setChl(channelArr[1]);
						channel.setAppChl(channelArr[2]);
						channel.setChannelRange(3);
					}
					channel.setCreateTime(date);
					channel.setCreateId(SecurityUtils.getUser().getId().longValue());
					insertList.add(channel);
				}
			}
			if (CollectionUtils.isNotEmpty(insertList)) {
				// 删除关系
				hbActivityCenterChannelMapper.delete(Wrappers.<HbActivityCenterChannel>lambdaQuery().eq(HbActivityCenterChannel::getActivityCenterId, activityCenterId));
				// 批量新增
				SqlHelper.executeBatch(HbActivityCenterChannel.class, MYBATIS_LOG, insertList, IService.DEFAULT_BATCH_SIZE, (session, entity) -> session.getMapper(HbActivityCenterChannelMapper.class).insert(entity));
			}
		}
		if (CollectionUtils.isNotEmpty(activityCenter.getGameDataList())) {
			// 更新游戏关系
			List<HbActivityCenterGame> insertList = Lists.newArrayList();
			HbActivityCenterGame game;
			for (String[] gameArr : activityCenter.getGameDataList()) {
				if (gameArr.length > 0) {
					game = new HbActivityCenterGame();
					game.setActivityCenterId(activityCenterId);
					if (1 == gameArr.length) {
						game.setParentGameId(Long.valueOf(gameArr[0]));
						game.setGameRange(1);
					}
					if (2 == gameArr.length) {
						game.setParentGameId(Long.valueOf(gameArr[0]));
						game.setChildGameId(Long.valueOf(gameArr[1]));
						game.setGameRange(2);
					}
					game.setCreateTime(date);
					game.setCreateId(SecurityUtils.getUser().getId().longValue());
					insertList.add(game);
				}
			}
			if (CollectionUtils.isNotEmpty(insertList)) {
				// 删除关系
				hbActivityCenterGameMapper.delete(Wrappers.<HbActivityCenterGame>lambdaQuery().eq(HbActivityCenterGame::getActivityCenterId, activityCenterId));
				// 批量新增
				SqlHelper.executeBatch(HbActivityCenterGame.class, MYBATIS_LOG, insertList, IService.DEFAULT_BATCH_SIZE, (session, entity) -> session.getMapper(HbActivityCenterGameMapper.class).insert(entity));
			}
		}
		if (CollectionUtils.isNotEmpty(activityCenter.getAreaDataList())) {
			// 更新区服关系
			List<HbActivityCenterArea> insertList = Lists.newArrayList();
			HbActivityCenterArea area;
			for (String[] areaArr : activityCenter.getAreaDataList()) {
				area = new HbActivityCenterArea();
				area.setActivityCenterId(activityCenterId);
				if (1 == areaArr.length) {
					area.setParentGameId(Long.valueOf(areaArr[0]));
					area.setAreaRange(1);
				}
				if (2 == areaArr.length) {
					area.setParentGameId(Long.valueOf(areaArr[0]));
					area.setAreaId(Long.valueOf(areaArr[1]));
					area.setAreaRange(2);
				}
				area.setCreateTime(date);
				area.setCreateId(SecurityUtils.getUser().getId().longValue());
				insertList.add(area);
			}
			if (CollectionUtils.isNotEmpty(insertList)) {
				// 删除关系
				hbActivityCenterAreaMapper.delete(Wrappers.<HbActivityCenterArea>lambdaQuery().eq(HbActivityCenterArea::getActivityCenterId, activityCenterId));
				// 批量新增
				SqlHelper.executeBatch(HbActivityCenterArea.class, MYBATIS_LOG, insertList, IService.DEFAULT_BATCH_SIZE, (session, entity) -> session.getMapper(HbActivityCenterAreaMapper.class).insert(entity));
			}
		}
	}
	public void findGameAreaChannel(Page<HbActivityCenterDO> page){
		if (CollectionUtil.isNotEmpty(page.getRecords())) {
			List<WanGameDO> gameList = gameDOMapperExt.selectList(new QueryWrapper<WanGameDO>().eq("isdelete", Constant.DEL_NO));
			List<NodeParentData> allParentChannelList = promotionChannelDOMapperExt.selectAllChannel();
			List<NodeParentData> allSubChannelList = wanGameChannelInfoDOMapperExt.selectAllSubNodeList();
			List<ParentGameArea> areaList = parentGameAreaMapper.selectList(new QueryWrapper<>());
			List<Long> activityCenterIds = page.getRecords().stream().map(HbActivityCenterDO::getId).collect(Collectors.toList());
			// 渠道
			List<HbActivityCenterChannel> activityCenterChannelList = hbActivityCenterChannelMapper.selectList(Wrappers.<HbActivityCenterChannel>lambdaQuery().in(HbActivityCenterChannel::getActivityCenterId,activityCenterIds).eq(HbActivityCenterChannel::getDeleted,0));
			// 游戏
			List<HbActivityCenterGame> activityCenterGameList = hbActivityCenterGameMapper.selectList(Wrappers.<HbActivityCenterGame>lambdaQuery().in(HbActivityCenterGame::getActivityCenterId,activityCenterIds).eq(HbActivityCenterGame::getDeleted,0));
			// 区服
			List<HbActivityCenterArea> activityCenterAreaList = hbActivityCenterAreaMapper.selectList(Wrappers.<HbActivityCenterArea>lambdaQuery().in(HbActivityCenterArea::getActivityCenterId,activityCenterIds).eq(HbActivityCenterArea::getDeleted,0));

			List<NodeParentData> childChannelList;
			List<NodeParentData> subChannelList;
			List<WanGameDO> childGameList;
			List<ParentGameArea> childAreaList;
			for (HbActivityCenterDO activityCenterDO : page.getRecords()) {
				List<HbActivityCenterChannel> activityChannelList = activityCenterChannelList.stream().filter(ac -> ac.getActivityCenterId().equals(activityCenterDO.getId())).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(activityChannelList)) {
					List<String[]> channelList = new ArrayList<>();
					String[] channelArr;
					for (HbActivityCenterChannel activityCenterChannel : activityChannelList) {
						if (1 == activityCenterChannel.getChannelRange()) {
							childChannelList = allParentChannelList.stream().filter(t -> StringUtils.isNotBlank(t.getPId()) && t.getPId().equalsIgnoreCase(activityCenterChannel.getParentChl())).collect(Collectors.toList());
							if (CollectionUtils.isNotEmpty(childChannelList)) {
								for (NodeParentData childChannel : childChannelList) {
									subChannelList = allSubChannelList.stream().filter(t -> StringUtils.isNotBlank(t.getPId()) && t.getPId().equalsIgnoreCase(childChannel.getNodeId())).collect(Collectors.toList());
									if (CollectionUtils.isNotEmpty(subChannelList)) {
										for (NodeParentData subChannel : subChannelList) {
											channelArr = new String[]{activityCenterChannel.getParentChl(), childChannel.getNodeId(), subChannel.getNodeId()};
											channelList.add(channelArr);
										}
									} else {
										channelArr = new String[]{activityCenterChannel.getParentChl(), childChannel.getNodeId()};
										channelList.add(channelArr);
									}
								}
							} else {
								channelArr = new String[]{activityCenterChannel.getParentChl()};
								channelList.add(channelArr);
							}
						} else if (2 == activityCenterChannel.getChannelRange()) {
							subChannelList = allSubChannelList.stream().filter(t -> StringUtils.isNotBlank(t.getPId()) && t.getPId().equals(activityCenterChannel.getChl())).collect(Collectors.toList());
							if (CollectionUtils.isNotEmpty(subChannelList)) {
								for (NodeParentData childChannel : subChannelList) {
									channelArr = new String[]{activityCenterChannel.getParentChl(), activityCenterChannel.getChl(), childChannel.getNodeId()};
									channelList.add(channelArr);
								}
							} else {
								channelArr = new String[]{activityCenterChannel.getParentChl(), activityCenterChannel.getChl()};
								channelList.add(channelArr);
							}
						} else if (3 == activityCenterChannel.getChannelRange()) {
							channelArr = new String[]{activityCenterChannel.getParentChl(), activityCenterChannel.getChl(), activityCenterChannel.getAppChl()};
							channelList.add(channelArr);
						}
					}
					activityCenterDO.setChannelDataList(channelList);
				}
				//游戏范围
				List<HbActivityCenterGame> centerGameList = activityCenterGameList.stream().filter(ac -> ac.getActivityCenterId().equals(activityCenterDO.getId())).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(centerGameList)) {
					List<Long[]> gameArrList = new ArrayList<>();
					Long[] gameArr;
					for (HbActivityCenterGame centerGame : centerGameList) {
						if (1 == centerGame.getGameRange()) {
							childGameList = gameList.stream().filter(t -> null != t.getPgid() && t.getPgid().equals(centerGame.getParentGameId())).collect(Collectors.toList());
							if (CollectionUtils.isNotEmpty(childGameList)) {
								for (WanGameDO game : childGameList) {
									gameArr = new Long[]{centerGame.getParentGameId(), game.getId()};
									gameArrList.add(gameArr);
								}
							} else {
								gameArr = new Long[]{centerGame.getParentGameId()};
								gameArrList.add(gameArr);
							}
						} else if (2 == centerGame.getGameRange()) {
							gameArr = new Long[]{centerGame.getParentGameId(), centerGame.getChildGameId()};
							gameArrList.add(gameArr);
						}
					}
					activityCenterDO.setGameDataList(gameArrList);
				}
				//游戏区服
				List<HbActivityCenterArea> centerAreaList = activityCenterAreaList.stream().filter(ac -> ac.getActivityCenterId().equals(activityCenterDO.getId())).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(centerAreaList)) {
					List<Long[]> areaArrList = new ArrayList<>();
					Long[] areaArr;
					for (HbActivityCenterArea centerArea : centerAreaList) {
						if (1 == centerArea.getAreaRange()) {
							childAreaList = areaList.stream().filter(t -> null != t.getParentGameId() && t.getParentGameId().equals(centerArea.getParentGameId())).collect(Collectors.toList());
							if (CollectionUtils.isNotEmpty(childAreaList)) {
								for (ParentGameArea area : childAreaList) {
									areaArr = new Long[]{centerArea.getParentGameId(), area.getAreaId()};
									areaArrList.add(areaArr);
								}
							} else {
								areaArr = new Long[]{centerArea.getParentGameId()};
								areaArrList.add(areaArr);
							}
						} else if (2 == centerArea.getAreaRange()) {
							areaArr = new Long[]{centerArea.getParentGameId(), centerArea.getAreaId()};
							areaArrList.add(areaArr);
						}
					}
					activityCenterDO.setAreaDataList(areaArrList);
				}
			}
		}
	}
}




